package com.mm.cloud.lease.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mm.cloud.common.core.enums.DeleteEnum;
import com.mm.cloud.common.core.enums.RoomLeaseEnum;
import com.mm.cloud.common.core.result.Result;
import com.mm.cloud.common.core.result.ResultUtil;
import com.mm.cloud.common.core.result.ResultConstants;
import com.mm.cloud.common.core.exception.BaseException;
import com.mm.cloud.common.redis.annotation.DistributionLock;
import com.mm.cloud.common.security.helper.LoginUserHelper;
import com.mm.cloud.common.security.loginuser.LoginUser;
import com.mm.cloud.lease.dto.tenant.form.SaveTenantDTO;
import com.mm.cloud.lease.dto.tenant.form.UpdateTenantDTO;
import com.mm.cloud.lease.entity.*;
import com.mm.cloud.lease.mapper.RoomMapper;
import com.mm.cloud.lease.mapper.TenantMapper;
import com.mm.cloud.lease.mapper.TenantOtherDepositMapper;
import com.mm.cloud.lease.mapper.TenantOtherFeeMapper;
import com.mm.cloud.lease.mapper.TenantOtherInfoMapper;
import com.mm.cloud.lease.service.ITenantService;
import com.mm.cloud.lease.service.impl.convert.tenant.TenantConvert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource;

/**
 * <p>
 * 租客 服务实现类
 * </p>
 *
 * @author mr
 * @since 2025-07-01
 */
@Service
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements ITenantService {

    @Resource
    private RoomMapper roomMapper;

    @Resource
    private TenantOtherDepositMapper tenantOtherDepositMapper;

    @Resource
    private TenantOtherFeeMapper tenantOtherFeeMapper;

    @Resource
    private TenantOtherInfoMapper tenantOtherInfoMapper;

    @Override
    @Transactional
    @DistributionLock(key = "ROOM:LEASE", paramName = "#dto.roomId", isReturn = true)
    public Result<Long> saveTenant(SaveTenantDTO dto) {
        // 获取登录上下文：用于绑定公司与操作人信息
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        // 前置校验：房间必须存在且未删除、未租
        checkRoomRentable(dto.getRoomId(), loginUser.getCompanyId());
        // 显式转换 DTO -> Entity，保持与其他模块一致的赋值规范
        Tenant tenant = TenantConvert.convert(dto);
        // 绑定公司与创建人；新增不设置 updateTime，由框架/数据库处理
        tenant.setCompanyId(loginUser.getCompanyId());
        tenant.setCreaterId(loginUser.getUserId());
        this.save(tenant);

        // 租客登记成功后：更新房间为“已租”
        Room room = new Room();
        room.setId(dto.getRoomId());
        room.setIsLease(RoomLeaseEnum.IS_LEASE.getStatus());
        roomMapper.updateById(room);

        // 保存租客附属信息（其他押金/其他付费/其他信息）
        saveOrReplaceOtherItemsOnCreate(tenant, loginUser.getCompanyId(), loginUser.getUserId(), dto);
        return ResultUtil.success(tenant.getId());
    }

    @Override
    public Result<String> updateTenant(UpdateTenantDTO dto) {
        // 获取登录上下文：用于绑定公司与操作人信息
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        // 显式转换 DTO -> Entity
        Tenant tenant = TenantConvert.convert(dto);
        // 绑定公司与修改人
        tenant.setCompanyId(loginUser.getCompanyId());
        tenant.setUpdaterId(loginUser.getUserId());
        this.updateById(tenant);

        // 替换保存租客附属信息
        replaceOtherItemsOnUpdate(tenant, loginUser.getCompanyId(), loginUser.getUserId(), dto);
        return ResultUtil.success();
    }

    /**
     * 新增时保存附属信息
     */
    private void saveOrReplaceOtherItemsOnCreate(Tenant tenant, Long companyId, Long userId, SaveTenantDTO dto) {
        // 其他押金
        if (dto.getOtherDepositList() != null) {
            dto.getOtherDepositList().forEach(item -> {
                com.mm.cloud.lease.entity.TenantOtherDeposit e = new TenantOtherDeposit();
                e.setCompanyId(companyId);
                e.setTenantId(tenant.getId());
                e.setDicId(item.getDicId());
                e.setDepositPrice(item.getDepositPrice());
                e.setCreaterId(userId);
                tenantOtherDepositMapper.insert(e);
            });
        }
        // 其他付费
        if (dto.getOtherFeeList() != null) {
            dto.getOtherFeeList().forEach(item -> {
                com.mm.cloud.lease.entity.TenantOtherFee e = new TenantOtherFee();
                e.setCompanyId(companyId);
                e.setTenantId(tenant.getId());
                e.setDicId(item.getDicId());
                e.setFeePrice(item.getFeePrice());
                e.setFeeMethod(item.getFeeMethod());
                e.setCreaterId(userId);
                tenantOtherFeeMapper.insert(e);
            });
        }
        // 其他信息
        if (dto.getOtherInfoList() != null) {
            dto.getOtherInfoList().forEach(item -> {
                com.mm.cloud.lease.entity.TenantOtherInfo e = new TenantOtherInfo();
                e.setCompanyId(companyId);
                e.setTenantId(tenant.getId());
                e.setDicId(item.getDicId());
                e.setInfoContent(item.getInfoContent());
                e.setCreaterId(userId);
                tenantOtherInfoMapper.insert(e);
            });
        }
    }

    /**
     * 修改时替换附属信息（先删后增）
     */
    private void replaceOtherItemsOnUpdate(Tenant tenant, Long companyId, Long userId, UpdateTenantDTO dto) {
        Long tenantId = tenant.getId();
        // 软删除旧记录或直接物理删除，这里做物理删除
        tenantOtherDepositMapper.delete(Wrappers.<TenantOtherDeposit>lambdaQuery()
                .eq(TenantOtherDeposit::getCompanyId, companyId)
                .eq(TenantOtherDeposit::getTenantId, tenantId));
        tenantOtherFeeMapper.delete(Wrappers.<TenantOtherFee>lambdaQuery()
                .eq(TenantOtherFee::getCompanyId, companyId)
                .eq(TenantOtherFee::getTenantId, tenantId));
        tenantOtherInfoMapper.delete(Wrappers.<TenantOtherInfo>lambdaQuery()
                .eq(TenantOtherInfo::getCompanyId, companyId)
                .eq(TenantOtherInfo::getTenantId, tenantId));

        // 重新插入
        SaveTenantDTO saveLike = new SaveTenantDTO();
        saveLike.setOtherDepositList(dto.getOtherDepositList());
        saveLike.setOtherFeeList(dto.getOtherFeeList());
        saveLike.setOtherInfoList(dto.getOtherInfoList());
        tenant.setId(tenantId);
        saveOrReplaceOtherItemsOnCreate(tenant, companyId, userId, saveLike);
    }

    /**
     * 校验房间是否允许登记租客：公司内存在、未删除、未租
     *
     * @param roomId    房间ID
     * @param companyId 公司ID
     */
    private void checkRoomRentable(Long roomId, Long companyId) {
        Room existRoom = roomMapper.selectOne(Wrappers.<Room>lambdaQuery()
                .eq(Room::getId, roomId)
                .eq(Room::getCompanyId, companyId));
        if (existRoom == null || !DeleteEnum.NOT_DELETE.getStatus().equals(existRoom.getIsDelete())) {
            throw new BaseException(ResultConstants.QUERY_NOT_FOUND_DATA);
        }
        if (!RoomLeaseEnum.NOT_LEASE.getStatus().equals(existRoom.getIsLease())) {
            throw new BaseException("房间已租，无法登记租客");
        }
    }
}
